// vue、element-ui、axios、js-base64、xlsx
declare var AMap: AMap;
declare global {
  interface AMap {
    [key: string]: any;
  }
}

let _engine = null;
export default function getEngineLoader(): any {
  if (_engine == null) {
    _engine = new EngineLoader();
  }
  return _engine;
}

import { Callback, IModal, IEngineLogic } from "../bean";
import { ILocation, ITablePageObj } from "../beanType";
import Engine from "./engine";
import Vue from "vue";

class EngineLayer extends Engine {
  _loadingInstance = null;

  init(logic: IEngineLogic, tag: string, isDebugMode: boolean, debugServer: number, mapKey: string, tokenUrl: string): void {
    super.init(logic, tag, isDebugMode, debugServer, mapKey, tokenUrl);
    this._setCurrentPlatform("web");
    this._initStorage();
  }

  toast(msg: any): void {
    if (!msg) {
      return;
    }
    Vue.instance.$message({
      center: true,
      message: typeof msg == "string" ? msg : msg + ""
    });
  }

  showLoading(msg?: string): void {
    if (this._loadingInstance) {
      if (this._loadingInstance.visible && this._loadingInstance.text == msg) {
        return;
      }
      this._loadingInstance.close();
    }
    this._loadingInstance = Vue.instance.$loading({
      text: msg || "加载中",
      fullscreen: true,
      spinner: "el-icon-loading",
      background: "rgba(0,0,0,0)"
    });
  }

  hideLoading(): void {
    if (this._loadingInstance) {
      this._loadingInstance.close();
      this._loadingInstance = null;
    }
  }

  showModal(param: IModal, callback?: typeof Callback): void {
    let option: any = {
      title: param.title,
      message: param.content,
      showCancelButton: (param.showCancel != undefined && param.showCancel != null) ? param.showCancel : true
    };
    if (param.cancelText) {
      option.cancelButtonText = param.cancelText;
    }
    if (param.confirmText) {
      option.confirmButtonText = param.confirmText;
    } else {
      option.confirmButtonText = "确定";
    }
    Vue.instance.$msgbox(option).then(function (data: any) {
      if (callback) {
        callback(true, null);
      }
    }).catch(function (reason: any) {
      if (callback) {
        callback(false, reason);
      }
    });
  }
}

class EngineLoader extends EngineLayer {

  getArrayByExcelFile(file: File, callback: typeof Callback, limitSize?: number): void {
    if (!callback) {
      return;
    }
    if (!file || !file.name) {
      callback(false, "文件不存在");
      return;
    }
    if (!file.name.endsWith(".xlsx") && !file.name.endsWith(".xls")) {
      callback(false, "请选择Excel类型的文件");
      return;
    }
    if (limitSize) {
      if (file.size > limitSize) {
        let size = limitSize > (1024 * 1024) ? limitSize / (1024 * 1024) + "M" : limitSize / 1024 + "KB";
        callback(false, "文件大小不能超过" + size);
        return;
      }
    } else {
      if (file.size > 10 * 1024 * 1024) {
        callback(false, "文件大小不能超过10M");
        return;
      }
    }
    let fileReader = new FileReader();
    fileReader.onload = function (ev: any) {
      try {
        let XLSX = require("xlsx");
        let data = ev.target.result;
        let workbook = XLSX.read(data, {
          type: "buffer" // binary、buffer、base64、string、array
        });
        let sheetArray: any[] = [];
        for (let sheet in workbook.Sheets) { // 各个表
          let itemArray = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
          if (itemArray && itemArray.length > 0) {
            sheetArray = sheetArray.concat(itemArray);
          }
        }
        callback(true, sheetArray);
      } catch (reason) {
        callback(false, reason);
      }
    };
    fileReader.readAsArrayBuffer(file);// fileReader.readAsBinaryString(file);
  }

  createTablePageObj(page?: number, pageSize?: number, pageTotal?: number): ITablePageObj {
    return new TablePageObj(page, pageSize, pageTotal);
  }

  downloadFile(url: string, param: object | null): void {
    let realUrl = url;
    if (param) {
      let query = null;
      for (let key in param) {
        let value = param[key];
        if (value && typeof value != "string") {
          try {
            value = JSON.stringify(value);
          } catch (error) { }
        }
        let jsbase = require("js-base64");
        value = jsbase.Base64.encode(value).replace(/\%/g, "%25").replace(/\+/g, "%2B").replace(/\"/g, "%22").replace(/\"/g, "%27").replace(/\//g, "%2F");
        if (!query) {
          query = "?";
        } else {
          query += "&";
        }
        query += key + "=" + value;
      }
      if (query) {
        realUrl += query;
      }
    }
    if (realUrl.startsWith("https")) {
      window.location.href = realUrl;
    } else {
      if (navigator && navigator.userAgent && navigator.userAgent.indexOf("Chrome") > -1) {
        window.open(realUrl);
      } else {
        window.location.href = realUrl;
      }
    }
  }

  getLocation(isShowLoading: boolean, param: ILocation, callback: typeof Callback): void {
    if (!callback) {
      return;
    }
    let hander = super.createAsynHandler();
    this.loadScript("https://webapi.amap.com/maps?v=1.4.15&key=" + this.getMapKey(), hander.register("location"));
    hander.getData(() => {
      if (isShowLoading) {
        this.showLoading();
      }
      AMap.plugin("AMap.Geolocation", () => {
        let geolocation = new AMap.Geolocation({
          enableHighAccuracy: true,
          timeout: 10000
        })
        let complete = AMap.event.addListener(geolocation, "complete", (data: any) => {
          if (isShowLoading) {
            this.hideLoading();
          }
          let result: any = {};
          if (data) {
            if (param.type >= 0) {
              if (data.position) {
                result.longitude = data.position.lng;
                result.latitude = data.position.lat;
              }
            }
            if (param.type >= 1) {
              if (data.addressComponent) {
                result.province = data.addressComponent.province;
                result.city = data.addressComponent.city;
                result.district = data.addressComponent.district;
              }
            }
            if (param.type >= 2) {
              result.address = data.formattedAddress;
            }
          }
          AMap.event.removeListener(complete);
          AMap.event.removeListener(error);
          callback(true, result);
        });
        let error = AMap.event.addListener(geolocation, "error", (reason: any) => {
          if (isShowLoading) {
            this.hideLoading();
          }
          AMap.event.removeListener(complete);
          AMap.event.removeListener(error);
          callback(false, reason);
        });
        geolocation.getCurrentPosition();
      });
    });
  }

}

class TablePageObj implements ITablePageObj {
  page = 1;
  pageSize = 10;
  pageTotal = 0;

  constructor(page: number | undefined | null, pageSize: number | undefined | null, pageTotal: number | undefined | null) {
    if (page != undefined && page != null) {
      this.page = page;
    }
    if (pageSize != undefined && pageSize != null) {
      this.pageSize = pageSize;
    }
    if (pageTotal != undefined && pageTotal != null) {
      this.pageTotal = pageTotal;
    }
  }
}